﻿#region Using Directives

    using System;
    using System.Xml;

#endregion

namespace MarketPulse.BusinessLogic.Legacy
{   
    /// <summary>
    /// Class used to process the XMl for an accreditation
    /// </summary>
    public class AccreditationXmlParser
    {
        #region Constants

            /// <summary>Constant value for No</summary>
            const string NO = "NO";

            /// <summary>Constant value for Yes</summary>
            const string YES = "YES";

            #endregion

        #region Member Variables

            /// <summary>The XML document for processing in this class</summary>
            private XmlDocument mXmlDocument;

            /// <summary>An xml node object used to represent a page within this class</summary>
            private XmlNode mPage;

            /// <summary>An xml node object used to represent a question within this class</summary>
            private XmlNode mQuestion;

            /// <summary>An xml node object used to represent an answer within this class</summary>
            private XmlNode mAnswer;

            /// <summary>An xml node object used to represent questions within this class</summary>
            private XmlNode mQuestions;

        #endregion

        #region Constructors

            /// <summary>
            /// Default constructor for this class
            /// </summary>
            public AccreditationXmlParser()
            {
            }

        #endregion

        #region Methods

            /// <summary>
            /// Method used to set up the values for the properties for a given page (used by an associated Accreditation object).
            /// </summary>
            /// <param name="pageNumber">An integer value used to represent the number of the page to retrieve the details for</param>
            public void ProcessPage(int pageNumber)
            {
                // Get the page from the xml
                mPage = mXmlDocument.SelectSingleNode("accreditation/page[@number= " + pageNumber + "]");

                // Get the question from the page xml
                if (mPage.SelectSingleNode("content[@type='QuestionAnswerHorizontal3Row']") == null && mPage.SelectSingleNode("content[@type='QuestionAnswerHorizontal']") == null && mPage.SelectSingleNode("content[@type='QuestionAnswerVertical']") == null)
                {
                    mQuestion = null;
                    mAnswer = null;
                }
                else
                {
                    // Get the question from the xml
                    mQuestion = mPage.SelectSingleNode("content/question");

                    // Get the answer from the xml
                    mAnswer = mQuestion.SelectSingleNode("answer");
                }

                if (mPage.SelectSingleNode("content[@type='QuestionAnswerTest']") == null)
                {
                    mQuestions = null;
                }
                else
                {
                    mQuestions = mPage.SelectSingleNode("content/questions");
                }
            }

            /// <summary>
            /// Method used to retrieve all questions for an accreditation
            /// </summary>                       
            /// <returns>A collection of questions for the page number supplied</returns>
            public QuestionCollection GetAllQuestions()
            {
                // Instantiate the return object
                QuestionCollection temporaryQuestions = new QuestionCollection();

                try
                {
                    foreach (XmlNode pages in mXmlDocument.SelectNodes("accreditation/page[@type='QuestionAnswerTest']"))
                    {
                        int pageNumber = int.Parse(pages.Attributes["number"].Value);

                        // Loop through the xml and create the questions for the page in question
                        foreach (XmlNode xmlNode in pages.SelectSingleNode("content/questions"))
                        {
                            temporaryQuestions.Add(GetQuestion(pageNumber, xmlNode));
                        }
                    }
                }
                catch (Exception)
                {
                    //TODO do something more meaningful here
                    throw;
                }
                return temporaryQuestions;
            }

            /// <summary>
            /// Method used to retrieve the display question and corresponding answers from the xml
            /// </summary>
            /// <returns>A valid (filled) AccreditationDisplayQuestion</returns>
            public AccreditationDisplayQuestion GetDisplayQuestion()
            {
                // Instantiate the return object
                AccreditationDisplayQuestion temporaryQuestion = new AccreditationDisplayQuestion();

                try
                {
                    temporaryQuestion.QuestionDisplayNumber = "Q.";
                    temporaryQuestion.QuestionText = mQuestion.SelectSingleNode("text").InnerText;
                    temporaryQuestion.QuestionInstructions = mQuestion.SelectSingleNode("instruction").InnerText;
                    temporaryQuestion.DisplayAnswers = GetDisplayAnswers();
                }
                catch (Exception)
                {
                    //TODO do something more meaningful here
                    throw;
                }
                return temporaryQuestion;
            }

            #region Local Methods

                /// <summary>
                /// Method used to retrieve a question object from the XML that represents it
                /// </summary>
                /// <param name="xmlNode">The Xml node to use to construct the question object</param>
                /// <returns>A valid (filled) Question object</returns>
            private Question GetQuestion(int pageNumber, XmlNode xmlNode)
            {
                // Instantiate the return object
                Question temporaryQuestion = new Question();

                try
                {
                    temporaryQuestion.ID = int.Parse(xmlNode.Attributes["QuestionID"].Value);
                    temporaryQuestion.Text = xmlNode.Attributes["QuestionText"].Value;
                    temporaryQuestion.Instructions = xmlNode.Attributes["QuestionNote"].Value;
                    temporaryQuestion.DisplayOrder = int.Parse(xmlNode.Attributes["DisplayOrder"].Value);
                    temporaryQuestion.DisplayNumber = int.Parse(xmlNode.Attributes["QuestionNumber"].Value);
                    temporaryQuestion.PossibleScore = int.Parse(xmlNode.Attributes["Score"].Value);
                    temporaryQuestion.AllowSelectAll = false;
                    temporaryQuestion.ContainerID = pageNumber;

                    // Set the response type for the question
                    switch (xmlNode.Attributes["AnswerType"].Value)
                    {
                        case "SingleChoice":
                            temporaryQuestion.QuestionResponseType = Question.ResponseType.SingleChoice;
                            break;
                        case "MultipleChoice":
                            temporaryQuestion.QuestionResponseType = Question.ResponseType.MultipleChoice;
                            break;
                        case "SelectAll":
                            temporaryQuestion.QuestionResponseType = Question.ResponseType.SelectAll;
                            temporaryQuestion.AllowSelectAll = true;
                            break;
                        case "FreeText":
                            temporaryQuestion.QuestionResponseType = Question.ResponseType.FreeText;
                            break;
                    }

                    // Get the answer options for the question
                    temporaryQuestion.AnswerOptions = GetAnswerOptions(xmlNode);
                }
                catch (Exception)
                {
                    //TODO do something more meaningful here
                    throw;
                }
                return temporaryQuestion;
            }

                /// <summary>
                /// Method used to retrieve the answer options for a given Question
                /// </summary>
                /// <param name="xmlNode">The xmlNode representing the question to get the answer options for</param>
                /// <returns>A valid AnswerOptionCollection object containing the answer options for the supplied question</returns>
                private AnswerOptionCollection GetAnswerOptions(XmlNode xmlNode)
                {
                    // Instantiate the return object
                    AnswerOptionCollection temporaryAnswerOptions = new AnswerOptionCollection();
                    try
                    {
                        // Make sure the question node has answer options
                        if (xmlNode.HasChildNodes)
                        {
                            // Move to the first node
                            xmlNode = xmlNode.FirstChild;

                            // Loop through the child nodes and create an answer option
                            foreach (XmlNode childNode in xmlNode)
                            {
                                AnswerOption answerOption = new AnswerOption();
                                answerOption.ID = int.Parse(childNode.Attributes["OptionID"].Value);
                                answerOption.Text = childNode.Attributes["AnswerText"].Value;
                                answerOption.Score = double.Parse(childNode.Attributes["Score"].Value); ;
                                answerOption.HasComment = childNode.Attributes["HasComment"].Value.Equals("Y") ? true : false;
                                answerOption.Dependant = 0;
                                answerOption.IsResponse = childNode.Attributes["Default"].Value.Equals("Y");

                                temporaryAnswerOptions.Add(answerOption);
                            }
                        }
                    }
                    catch (Exception)
                    {
                        //TODO do something more meaningful here
                        throw;
                    }
                    return temporaryAnswerOptions;
                }

                /// <summary>
                /// Method used to retrieve the Display Question answers from the XML
                /// </summary>
                /// <returns>A valid (filled) AccreditationDisplayAnswerCollection item</returns>
                private AccreditationDisplayAnswerCollection GetDisplayAnswers()
                {
                    // Instantiate the return object
                    AccreditationDisplayAnswerCollection temporaryAnswers = new AccreditationDisplayAnswerCollection();

                    try
                    {                                    
                        if (mPage.SelectSingleNode("content[@type='QuestionAnswerHorizontal3Row']") != null) 
                        {
                            try
                            {

                                temporaryAnswers.Add(GetDisplayAnswer(YES, mQuestion.SelectSingleNode("answer[@value='" + YES + "']")));
                                temporaryAnswers.Add(GetDisplayAnswer(NO, mQuestion.SelectSingleNode("answer[@value='" + NO + "']")));

                                temporaryAnswers.Add(GetDisplayAnswer(YES, mQuestion.SelectSingleNode("answer[@value='" + YES + "']").NextSibling));
                                temporaryAnswers.Add(GetDisplayAnswer(NO, mQuestion.SelectSingleNode("answer[@value='" + NO + "']").NextSibling));

                                temporaryAnswers.Add(GetDisplayAnswer(YES, mQuestion.SelectSingleNode("answer[@value='" + YES + "']").NextSibling.NextSibling));
                                temporaryAnswers.Add(GetDisplayAnswer(NO, mQuestion.SelectSingleNode("answer[@value='" + NO + "']").NextSibling.NextSibling));
                            }
                            catch (Exception)
                            {
                                temporaryAnswers.RemoveAt(temporaryAnswers.Count - 1);
                                return temporaryAnswers;
                            }
                                        
                        }
                        else 
                        {
                            temporaryAnswers.Add(GetDisplayAnswer(YES, mQuestion.SelectSingleNode("answer[@value='" + YES + "']")));
                            temporaryAnswers.Add(GetDisplayAnswer(NO, mQuestion.SelectSingleNode("answer[@value='" + NO + "']")));                                        
                        }
                    }
                    catch (Exception)
                    {
                        //TODO do something more meaningful here
                        throw;
                    }
                    return temporaryAnswers;
                }

                /// <summary>
                /// Method used to retrieve a display answer based on the type supplied
                /// </summary>
                /// <param name="type">The type of answer to retrieve</param>
                /// <returns>A valid (filled) display answer item</returns>
                private AccreditationDisplayAnswer GetDisplayAnswer(string type, XmlNode displayAnswer)
                {
                    // Instantiate a return object
                    AccreditationDisplayAnswer temporaryAnswer = new AccreditationDisplayAnswer();
                    try
                    {
                        // Set some values based on the XML
                        var textElement = displayAnswer.SelectSingleNode("text");
                        if (displayAnswer.Attributes["title"] != null)
                            temporaryAnswer.Title = displayAnswer.Attributes["title"].Value;
                        temporaryAnswer.AnswerText = textElement.InnerText;
                        if (textElement.Attributes["cssClass"] != null)
                            temporaryAnswer.AnswerTextCssClass = textElement.Attributes["cssClass"].Value;
                        if (displayAnswer.Attributes["backColor"] != null)
                            temporaryAnswer.AnswerBackColor = displayAnswer.Attributes["backColor"].Value;
                        temporaryAnswer.AnswerImageText = displayAnswer.Attributes["imageText"].Value;
                        temporaryAnswer.AnswerImage = displayAnswer.Attributes["image"].Value;
                        if (displayAnswer.Attributes["height"] != null)
                            temporaryAnswer.Height = displayAnswer.Attributes["height"].Value;
                        if (displayAnswer.Attributes["showImageTips"] != null)
                            temporaryAnswer.ShowImageTips = displayAnswer.Attributes["showImageTips"].Value;                                    
                        temporaryAnswer.AnswerLabel = type;

                    }
                    catch (Exception)
                    {
                        //TODO do something more meaningful here
                        throw;
                    }
                    return temporaryAnswer;
                }

            #endregion

        #endregion

        #region Properties

            /// <summary>The XML document to be processed</summary>
            public XmlDocument Xml { set { mXmlDocument = value; } }

            /// <summary>The title of the Accreditation represented by the Xml in this class</summary>
            public string Title { get { if (mXmlDocument != null) return mXmlDocument.SelectSingleNode("accreditation").Attributes["title"].Value; else return string.Empty; } }

            /// <summary>The number of pages available for the Accreditation represented by the Xml in this class</summary>
            public int PageCount { get { if (mXmlDocument != null) return (mXmlDocument.SelectNodes("accreditation/page").Count); else return 0; } }

            /// <summary>The Page Type</summary>
            public string PageType { get { if (mPage != null) return mPage.Attributes["type"].Value; else return string.Empty; } }

            /// <summary>The Page Title</summary>
            public string PageTitle { get { if (mPage != null) return mPage.Attributes["title"].Value; else return string.Empty; } }

            /// <summary>The Page Content Type</summary>
            public string PageContentType { get { if (mPage != null) return mPage.SelectSingleNode("content").Attributes["type"].Value; else return string.Empty; } }

            /// <summary>The Banner Image </summary>
            public string BannerImage { get { if (mPage != null) return "Accreditations/" + Title + "/Images/Banners/" + mPage.SelectSingleNode("banner").Attributes["image"].Value; else return string.Empty; } }

            /// <summary>The Banner title </summary>
            public string BannerTitle { get { if (mPage != null) return mPage.SelectSingleNode("banner").Attributes["title"].Value; else return string.Empty; } }

            /// <summary>The Sidebar Title </summary>
            public string SidebarTitle { get { if (mPage != null) return mPage.SelectSingleNode("sidebar").Attributes["title"].Value; else return string.Empty; } }

            /// <summary>The Sidbar Image </summary>
            public string SidebarImage { get { if (mPage != null) return "Accreditations/" + Title + "/Images/Sidebar/" + mPage.SelectSingleNode("sidebar").Attributes["image"].Value; else return string.Empty; } }

            /// <summary>The Content Image </summary>
            public string ContentTitle { get { if (mPage != null) return mPage.SelectSingleNode("content").Attributes["title"].Value; else return string.Empty; } }

            /// <summary>The Content Text </summary>
            public string ContentText { get { if (mPage != null) return mPage.SelectSingleNode("content").InnerText; else return string.Empty; } }

            /// <summary>The Instruction Text </summary>
            public string InstructionText { get { if (mQuestion != null) return mQuestion.SelectSingleNode("instruction").InnerText; else return string.Empty; } }

            /// <summary>The Question Text </summary>
            public string QuestionText { get { if (mQuestion != null) return mQuestion.SelectSingleNode("text").InnerText; else return string.Empty; } }

            /// <summary>The Image ALT </summary>
            public string ImageALT { get { if (mAnswer != null) return mAnswer.Attributes["imageText"].Value; else return string.Empty; } }

            /// <summary>The Image SRC </summary>
            public string ImageSRC { get { if (mAnswer != null) return mAnswer.Attributes["image"].Value; else return string.Empty; } }

            /// <summary>Question Xml </summary>
            public XmlNode QuestionNode { get { return mQuestion; } }

            /// <summary>Get the number for the success page</summary>
            public int SuccessPageNumber { get { if (mXmlDocument != null) return int.Parse(mXmlDocument.SelectSingleNode("accreditation/page[@type='Pass']").Attributes["number"].Value); else return 0; } }
                    
            /// <summary>Get the number for the fail page</summary>
            public int FailPageNumber { get { if (mXmlDocument != null) return int.Parse(mXmlDocument.SelectSingleNode("accreditation/page[@type='Fail']").Attributes["number"].Value); else return 0; } }

        #endregion
    }         
}
